package KVService;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;

import com.google.common.io.Files;



import org.apache.*;

public class Lucene {
	
	private IndexWriter writer;
	private IndexWriterConfig iwc;
	private Directory dir;
	private String dirName;
	
	
	public Lucene() throws IOException{
		
		// create index director
		File tmpDir = Files.createTempDir();
		dirName = tmpDir.getAbsolutePath();
		System.out.println("Lucene dir name: " + dirName);
		dir = FSDirectory.open(tmpDir);

		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
		
		iwc = new IndexWriterConfig(Version.LUCENE_40, analyzer);
		
		iwc.setOpenMode(OpenMode.CREATE);
		
		// initialize index
		writer = new IndexWriter(dir, iwc);
		writer.close();
		writer = null;
	}
	
	public synchronized IndexWriter getIndexWriter() throws IOException {
        if (writer == null) {
        	writer = new IndexWriter(dir, iwc);
        }
        return writer;
	}    
   
    public synchronized void closeIndexWriter() throws IOException {
		if (writer != null) {
			writer.close();
		}
    }
	
	public synchronized void  index(int key, String data) throws CorruptIndexException, IOException{
		// make a new, empty document
		Document doc = new Document();
		
		// Add key to doc properties
		Field keyField = new StringField("key", Integer.toString(key), Field.Store.YES);
		doc.add(keyField);
		
		doc.add(new TextField("contents", new BufferedReader(new StringReader(data)), Field.Store.NO));
		
		// New index, so we just add the document (no old document can be there):
		getIndexWriter().addDocument(doc);
		
	}
	
	public synchronized ArrayList<Integer> search(String queryString) throws IOException, ParseException{
		closeIndexWriter();
		
		Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
		QueryParser parser = new QueryParser(Version.LUCENE_40, "contents", analyzer);
		IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(dirName)));
		IndexSearcher searcher = new IndexSearcher(reader);
		Query query = parser.parse(queryString);
	    TopDocs hits = searcher.search(query, 10);
	    ArrayList<Integer> results = new ArrayList<Integer>();
	    
		for(ScoreDoc sd : hits.scoreDocs){
			Document d = searcher.doc(sd.doc);
			results.add(Integer.parseInt(d.get("key")));
		}
		
		return results;
	}

	
	/**
	 * Main entry point
	 * 
	 * @param args variable argument list
	 * @throws IOException 
	 * @throws ParseException 
	 */
	public static void main(String[] args) throws IOException, ParseException {
		
		Lucene lucene = new Lucene();
		
		lucene.index(1, "Test movie title");
		lucene.index(2, "Best film ever");
		lucene.index(3, "Scary movie");
		
		String query = "movie";
		ArrayList<Integer> results = lucene.search(query);
		
		for(int i : results){
			System.out.println("Search for \"" + query + "\" returned key " + i);
		}
		
		query = "test movie";
		results = lucene.search(query);
		
		for(int i : results){
			System.out.println("Search for \"" + query + "\" returned key " + i);
		}
		
	}

}